package com.sinosoft.vaccinetoai.exception.handler;

import cn.hutool.core.util.StrUtil;
import com.sinosoft.vaccinetoai.exception.BusinessException;
import com.sinosoft.vaccinetoai.common.ApiResult;
import com.sinosoft.vaccinetoai.exception.ExceptionEnums;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 异常处理
 * @author xzh
 * @date 2022-10-24 11:25
 * @since 5.0.0
 */
@Slf4j
@RestControllerAdvice(basePackages = "com.sinosoft.vaccinetoai")
public class CustomExceptionHandlerAdvice {

    /**
     * 异常处理方法
     * 将异常转换为相关结果返回给调用方
     * @param exception 需要处理的异常
     * @return {@link ApiResult } 结果
     * @author xzh
     * @since 5.0.0
     */
    @ExceptionHandler(value = Exception.class)
    public ApiResult handle(Exception exception) {
        ApiResult apiResult = null;
        // 业务异常
        if(exception instanceof BusinessException) {
            apiResult = ApiResult.ofBusinessException((BusinessException) exception);
        }
        // 处理参数绑定异常
        else if (exception instanceof MethodArgumentNotValidException) {
            apiResult = ApiResult.ofExceptionEnums(ExceptionEnums.PARAMS_INVALID);
            // 组装参数错误信息
            MethodArgumentNotValidException argumentException = (MethodArgumentNotValidException) exception;
            List<FieldError> errorList = argumentException.getBindingResult().getFieldErrors();
            List<String> msgList = errorList.stream().map(FieldError::getDefaultMessage).collect(Collectors.toList());
            // 返回参数错误信息
            apiResult.setMessage(StrUtil.join("；", msgList));
        }else if (exception instanceof BindException){
            apiResult = ApiResult.ofExceptionEnums(ExceptionEnums.PARAMS_INVALID);
            // 组装参数错误信息
            BindException argumentException = (BindException) exception;
            List<FieldError> errorList = argumentException.getBindingResult().getFieldErrors();
            List<String> msgList = errorList.stream().map(FieldError::getDefaultMessage).collect(Collectors.toList());
            // 返回参数错误信息
            apiResult.setMessage(StrUtil.join("；", msgList));
        }
        // 鉴权失败
        else if (exception.getClass().getName().equals("org.apache.shiro.authz.UnauthorizedException")) {
            log.error("出现鉴权异常 - {}", exception.getMessage());
            apiResult = ApiResult.ofExceptionEnums(ExceptionEnums.AUTH_UNAUTHORIZED);
        }
        // 其他异常
        else {
            log.error("出现异常", exception);
            apiResult = ApiResult.ofExceptionEnums(ExceptionEnums.ERROR);
        }
        log.debug("异常处理：{}", exception.getClass().getName());

        return apiResult;
    }

}
